<template>
  <div id="webGisMap"></div>
  <div class="bottomBox">
    <button class="ml-10" @click="drawLine()">绘制线</button>
    <button class="ml-10 mt-10" @click="drawText()">绘制文字</button>
    <button class="ml-10 mt-10" @click="drawFlicker()">绘制闪烁</button>
  </div>
</template>
<script setup>
import mapboxGl from "mapbox-gl";
import config from "./config.js";
import { onMounted, ref } from "vue";
import { getLine } from "@/api/index.js";
import utils from "./utils.js";
import { openLoading } from "@/utils/common.js";
import mapDotImg from "@/assets/images/mc.png";
let map;
/** 初始化地图 */
const initMap = () => {
  mapboxGl.accessToken = config.accessToken;
  map = new mapboxGl.Map(config.map);
  map.on("style.load", () => {
    map.on("click", (e) => {
      mapClick(e, "click");
    });
    // 添加地形源
    map.addSource("mapbox-dem", {
      type: "raster-dem",
      url: "mapbox://mapbox.mapbox-terrain-dem-v1",
      tileSize: 512,
    });

    // 启用地形
    map.setTerrain({
      source: "mapbox-dem",
      exaggeration: 2,
    });

    // 添加3D建筑
    // 添加3D建筑（现在composite源可用）
    if (map.getSource("composite")) {
      // 安全检测
      map.addLayer({
        id: "3d-buildings",
        source: "composite",
        "source-layer": "building",
        type: "fill-extrusion",
        paint: {
          "fill-extrusion-color": "#ddd",
          "fill-extrusion-height": ["get", "height"],
          "fill-extrusion-base": ["get", "min_height"],
          "fill-extrusion-opacity": 0.6,
        },
      });
    }

    // 监听缩放事件
    map.on("zoom", () => {
      //判断是否有绘画监测点名称
      if (map.getLayer("point-monitoringNames-layer")) {
        const zoomLevel = map.getZoom(); // 获取当前缩放层级
        // 检查当前缩放层级
        if (zoomLevel >= 17) {
          // 如果层级为 17 或更高，开启 text-allow-overlap 属性
          map.setLayoutProperty(
            "point-monitoringNames-layer",
            "text-allow-overlap",
            true
          );
        } else {
          // 如果层级低于 17，关闭该属性
          map.setLayoutProperty(
            "point-monitoringNames-layer",
            "text-allow-overlap",
            false
          );
        }
      }
    });

    map.on("load", () => {
      // 当地图加载完成后执行的操作
    });

    // map.on('mousemove', (e) => {
    //   mapClick(e, 'mousemove');
    // });
  });
};

const mapClick = (e, t) => {
  if (t === "click") console.log("click", e.lngLat);
};
const { MapboxLayer, TripsLayer } = deck;
/** 添加流动线 */
const addFlowLine = (features = []) => {
  let maxTime = 20;
  const newList = features.filter((item) => {
    if (item.geometry?.coordinates && item.properties.length > 100) {
      return item;
    }
  });
  const result = newList.map((row) => {
    let startTime = 0;
    return {
      vendor: 0,
      path: row.geometry.coordinates,
      timestamps: row.geometry.coordinates.map(() => {
        startTime += 20;
        maxTime = startTime > maxTime ? startTime : maxTime;
        return startTime;
      }),
    };
  });

  // 添加流动线层
  const deckLayer = new MapboxLayer({
    id: config.lineFlowLayer.id,
    type: TripsLayer,
    data: result,
    getPath: (d) => d.path,
    getTimestamps: (d) => d.timestamps, // 该时间数组对应流动线条应该在什么时间点移动到对应下标的坐标点
    getColor: () => config.lineFlowLayer.color,
    ...config.lineFlowLayer,
  });
  utils.delLayer(map, config.lineFlowLayer);
  map.addLayer(deckLayer);
  let isShowLine = true;
  // 循环更新动画
  const animate = () => {
    config.lineFlowLayer.time =
      (config.lineFlowLayer.time + config.lineFlowLayer.animationSpeed) %
      config.lineFlowLayer.loopLength;
    if (config.lineFlowLayer.time >= maxTime) config.lineFlowLayer.time = 20;
    deckLayer.setProps({
      currentTime: config.lineFlowLayer.time,
    });
    if (isShowLine) window.requestAnimationFrame(animate);
  };
  setTimeout(() => {
    if (isShowLine) window.requestAnimationFrame(animate);
  }, 200);
};

/**绘画线*/
const drawLine = async () => {
  let load = openLoading("数据正在加载中...");
  let res = await getLine();
  let coordinates = res.data.map((item) => {
    return item.pipeLocations.map((location) => [
      parseFloat(location.longitude),
      parseFloat(location.latitude),
    ]);
  });
  //白色的边框
  utils.setLine(map, "line-source-fff", coordinates);
  utils.setLine(map, "line-source", coordinates);

  map.addLayer(config.lineLayerFFF);
  // 添加线条图层
  map.addLayer(config.lineLayer);

  let lines = utils.getLines(res.data);
  addFlowLine(lines);
  load.close();
};

/**绘制文字*/
const drawText = () => {
  // utils.addText();
  // if (map.getLayer("point-layer")) {
  //   map.removeLayer("point-layer");
  // }

  // if (map.getLayer("text-layer")) {
  //   map.removeLayer("text-layer");
  // }

  if (map.getSource("markers")) {
    //有就切换显示和隐藏
    //注意：如果创建图层的时候没有添加visibility属性，getLayoutProperty获取到的将是一个undefined
    const visibility = map.getLayoutProperty("point-layer", "visibility");
    console.log("visibility", visibility);
    // 如果当前是 'visible'，则隐藏，否则显示
    if (visibility === "visible") {
      map.setLayoutProperty("point-layer", "visibility", "none");
      map.setLayoutProperty("text-layer", "visibility", "none");
      map.setLayoutProperty("imageLayer", "visibility", "none");
    } else {
      map.setLayoutProperty("point-layer", "visibility", "visible");
      map.setLayoutProperty("text-layer", "visibility", "visible");
      map.setLayoutProperty("imageLayer", "visibility", "visible");
    }
  } else {
    //没有就创建
    // 添加数据源（GeoJSON格式）
    map.addSource("markers", {
      type: "geojson",
      data: {
        type: "FeatureCollection",
        features: [
          {
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [105.93091372260528, 26.333194972648016], // 点坐标
            },
            properties: {
              title: "重要地点", // 要显示的文字
              description: "示例位置",
            },
          },
        ],
      },
    });

    //向地图中添加图片，可在使用到图片的地方直接使用图片id("image_id")
    map.loadImage(mapDotImg, (error, image) => {
      if (error) throw error;
      map.addImage("image_id", image);
    });

    // 添加圆点图层（显示在文字下方）
    map.addLayer({
      id: "point-layer",
      type: "circle",
      source: "markers", //相同的source
      layout: {
        visibility: "visible",
      },
      paint: {
        "circle-radius": 5, // 点的大小
        "circle-color": "#ff0000", // 红色圆点
        "circle-stroke-width": 2,
        "circle-stroke-color": "#fff",
      },
    });

    // 添加文字图层
    map.addLayer({
      id: "text-layer",
      type: "symbol",
      source: "markers", //相同的source
      layout: {
        visibility: "visible",
        "text-field": ["get", "title"], // 显示 properties.title
        "text-size": 13,
        "text-offset": [0, 2.5], // 关键：向上偏移文字（负Y值）
        "text-anchor": "bottom", // 文字锚点在底部
      },
      paint: {
        "text-color": "#615118",
        "text-halo-color": "#fff",
        "text-halo-width": 2,
      },
    });
    // 添加图片图层
    map.addLayer({
      id: "imageLayer",
      type: "symbol",
      source: "markers", //相同的source
      layout: {
        visibility: "visible", //visibility：控制元素的显示和隐藏 visible显示 none隐藏
        "icon-image": "image_id", // 使用之前添加的图片ID
        "icon-size": 0.5, // 调整大小
        "icon-offset": [100, 0], // 关键：向上偏移文字（负Y值）
      },
    });
  }
};

/**绘制异常闪烁*/
const drawFlicker = () => {
  const pulsingDotTow = drawCanvas("rgba(255, 0, 0, 0.5)", map, 150);
  map.addImage("pulsing-dot1", pulsingDotTow, { pixelRatio: 2 });

  // 添加数据源（GeoJSON格式）
  map.addSource("abnormalPointLocation", {
    type: "geojson",
    data: {
      type: "FeatureCollection",
      features: [
        {
          type: "Feature",
          geometry: {
            type: "Point",
            coordinates: [105.93099372260528, 26.333194978648016], // 点坐标
          },
          properties: {
            title: "重要地点", // 要显示的文字
            description: "示例位置",
          },
        },
      ],
    },
  });

  map.addLayer({
    id: "abnormalPointLocation1",
    type: "symbol",
    source: "abnormalPointLocation",
    layout: {
      "icon-image": "pulsing-dot1",
      "icon-allow-overlap": true, // 允许重叠
    },
  }); //异常监测点
};

// 绘制canvas
function drawCanvas(color, map, sizeNum = 100) {
  const size = sizeNum;
  return {
    width: size,
    height: size,
    data: new Uint8Array(size * size * 4),

    onAdd: function () {
      const canvas = document.createElement("canvas");
      canvas.width = this.width;
      canvas.height = this.height;
      this.context = canvas.getContext("2d");
    },

    render: function () {
      const duration = 1000;
      const t = (performance.now() % duration) / duration;

      const radius = (size / 2) * 0.3;
      const outerRadius = (size / 2) * 0.7 * t + radius;
      const context = this.context;

      // draw outer circle
      context.clearRect(0, 0, this.width, this.height);
      context.beginPath();
      context.arc(this.width / 2, this.height / 2, outerRadius, 0, Math.PI * 2);
      context.fillStyle = color;
      context.fill();

      this.data = context.getImageData(0, 0, this.width, this.height).data;
      map.triggerRepaint();
      return true;
    },
  };
}
onMounted(() => {
  initMap();
});
</script>
<style lang="scss" scoped>
#webGisMap {
  width: 100%;
  height: 100vh;
}
.bottomBox {
  position: fixed;
  top: 10px;
  z-index: 99;
  left: 0px;
  width: 100px;
}
</style>

